package com.open.capacity.user.controller;

import com.open.capacity.annotation.log.LogAnnotation;
import com.open.capacity.commons.Result;
import com.open.capacity.model.system.*;
import com.open.capacity.user.model.Sys3auth;
import com.open.capacity.user.service.Sys3authService;
import com.open.capacity.user.service.SysMenuService;
import com.open.capacity.user.vo.SysMenuExtVo;
import com.open.capacity.vo.SysMenuVo;
import com.open.capacity.utils.SysUserUtil;
import com.open.capacity.vo.TreeVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.collections.list.TreeList;
import org.apache.commons.lang3.ObjectUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

@RestController
@Api(tags = "菜单模块api")
public class SysMenuController {
    private static Logger logger = LoggerFactory.getLogger(SysMenuController.class);

    @Autowired
    private SysMenuService menuService;

    @Autowired
    private Sys3authService authService;


    @PreAuthorize("hasAuthority('menu:get/menus/tree')")
    @ApiOperation(value = "查询菜单tree")
    @GetMapping("/menus/tree")
    public Result<List<TreeVo>> treeMenus(@RequestParam(value = "target", required = false) String target) {
        Map<String, Object> params = new HashMap<>();
        params.put("target", target);
        List<SysMenu> menus = menuService.findMenus(params);
        List<TreeVo> treeList = new TreeList();
        menus.forEach(m -> {
            TreeVo node = new TreeVo();
            node.setId(m.getId().toString());
            node.setText(m.getName());
            node.setValue(m.getId().toString());
            node.setShowcheck(false);
            node.setCheckstate(0);
            node.setIsexpand(false);
            node.setIcon(m.getCss());
            node.setComplete(true);
            node.setParentId(m.getParentId().toString());
            treeList.add(node);
        });
        return Result.succeed(TreeVo.RecursiveBuilder(treeList));
    }


    /**
     * 查询菜单list
     *
     * @param parentId
     * @return
     */
    @PreAuthorize("hasAuthority('menu:get/menus/list')")
    @ApiOperation(value = "查询菜单list")
    @GetMapping("/menus/list")
    public Result<List<SysMenu>> listMenus(@RequestParam(value = "parentId", defaultValue = "0") String parentId, @RequestParam(value = "keyword", required = false) String keyword) {
        Map<String, Object> params = new HashMap<>();
        params.put("parentId", parentId);
        params.put("keyword", keyword);
        List<SysMenu> companys = menuService.findMenus(params);
        return Result.succeed(companys);
    }


    @PreAuthorize("hasAuthority('menu:get/menus/authorizeTree')")
    @ApiOperation(value = "查询授权菜单tree")
    @GetMapping("/menus/authorizeTree")
    public Result<SysMenuExtVo> treeAuthorizeMenus() {
        Map<String, Object> params = new HashMap<>();
        params.put("category", 0);
        List<SysMenuVo> menus = menuService.findAll(params);
        List<TreeVo> menuList = new TreeList();
        List<TreeVo> buttonList = new TreeList();
        List<TreeVo> columnList = new TreeList();
        List<TreeVo> formList = new TreeList();
        menus.forEach(m -> {
            TreeVo node = new TreeVo();
            TreeVo button = new TreeVo();
            TreeVo column = new TreeVo();
            TreeVo form = new TreeVo();
            SysMenu menu = m.getMenu();
            node.setId(menu.getId() + "_learun_moduleId");
            node.setText(menu.getName());
            node.setValue(menu.getId());
            node.setShowcheck(true);
            node.setCheckstate(0);
            node.setIsexpand(true);
            node.setIcon(menu.getCss());
            node.setComplete(true);
            node.setParentId(menu.getParentId().equals("0") ? "0" : (menu.getParentId() + "_learun_moduleId"));
            BeanUtils.copyProperties(node, button);
            BeanUtils.copyProperties(node, column);
            BeanUtils.copyProperties(node, form);

            menuList.add(node);
            buttonList.add(button);
            columnList.add(column);
            formList.add(form);
            if (!CollectionUtils.isEmpty(m.getMenuBtns())) {
                m.getMenuBtns().forEach(b -> {
                    TreeVo btnNode = new TreeVo();
                    btnNode.setId(b.getId());
                    btnNode.setText(b.getName());
                    btnNode.setValue(b.getId());
                    btnNode.setShowcheck(true);
                    btnNode.setCheckstate(0);
                    btnNode.setIsexpand(false);
                    btnNode.setIcon(b.getCss());
                    btnNode.setComplete(true);
                    btnNode.setParentId(b.getParentId().equals("0") ? (menu.getId() + "_learun_moduleId") : b.getParentId());
                    buttonList.add(btnNode);
                });
            }
            if (!CollectionUtils.isEmpty(m.getMenuColumns())) {
                m.getMenuColumns().forEach(c -> {
                    TreeVo columnNode = new TreeVo();
                    columnNode.setId(c.getId());
                    columnNode.setText(c.getName());
                    columnNode.setValue(c.getId());
                    columnNode.setShowcheck(true);
                    columnNode.setCheckstate(0);
                    columnNode.setIsexpand(false);
                    columnNode.setComplete(true);
                    columnNode.setParentId(menu.getId() + "_learun_moduleId");
                    columnList.add(columnNode);
                });
            }
        });
        List<TreeVo> menuTree = TreeVo.RecursiveBuilder(menuList);
        List<TreeVo> buttonTree = TreeVo.RecursiveBuilder(buttonList);
        List<TreeVo> columnTree = TreeVo.RecursiveBuilder(columnList);
        SysMenuExtVo vo = new SysMenuExtVo();
        vo.setMenuList(menuTree);
        vo.setButtonList(buttonTree);
        vo.setColumnList(columnTree);
        return Result.succeed(vo);
    }


    @ApiOperation(value = "获取菜单")
    @PreAuthorize("hasAuthority('menu:get/menus/{id}')")
    @GetMapping("/menus/{id}")
    public Result<SysMenuVo> findMenuById(@PathVariable(value = "id") String id) {
        SysMenuVo menu = menuService.findById(id);
        return Result.succeed(menu);
    }

    @ApiOperation(value = "获取菜单按钮")
    @PreAuthorize("hasAuthority('menu:get/menus/{id}/findButtons')")
    @GetMapping("/menus/{id}/findButtons")
    public Result<Set<SysMenuButton>> findMenuButtonsById(@PathVariable(value = "id") String id) {
        SysMenuVo menu = menuService.findById(id);
        return Result.succeed(menu.getMenuBtns());
    }

    @ApiOperation(value = "根据path获取菜单")
    @PreAuthorize("hasAuthority('menu:get/menus/findByPath')")
    @GetMapping("/menus/findByPath")
    public Result findMenuByPath(String path) {
        SysMenu menu = menuService.findByPath(path);
        return Result.succeed(menu);
    }


    /**
     * 保存菜单
     *
     * @param sysMenu 菜单
     * @return
     */
    @PreAuthorize("hasAnyAuthority('menu:post/menus','menu:put/menus')")
    @ApiOperation(value = "保存菜单")
    @PostMapping("/menus/saveOrUpdate")
    @LogAnnotation(module = "系统菜单", name = "更新")
    public Result<String> saveOrUpdate(@RequestBody SysMenuVo sysMenu) {
        try {
            SysMenu menu = new SysMenu();
            BeanUtils.copyProperties(sysMenu.getMenu(), menu);
            Set<SysMenuButton> btns = sysMenu.getMenuBtns();
            Set<SysMenuColumn> cols = sysMenu.getMenuColumns();
            return menuService.saveOrUpdate(menu, btns, cols);
        } catch (Exception ex) {
            ex.printStackTrace();
            return Result.failed("操作失败");
        }
    }

    /**
     * 当前登录用户的菜单
     *
     * @return
     */
    @PreAuthorize("hasAuthority('menu:get/menus/current')")
    @GetMapping("/menus/current")
    @ApiOperation(value = "查询当前用户菜单")
    public List<SysMenu> findMyMenu() {
        LoginAppUser loginAppUser = SysUserUtil.getLoginAppUser();
        Set<SysRole> roles = loginAppUser.getSysRoles();
        List<SysMenu> menus = new ArrayList<>();
        if (loginAppUser.getId().equals("1")) {
            Map<String, Object> params = new HashMap<>();
            menus = menuService.findMenus(params);
        } else if (!CollectionUtils.isEmpty(roles)) {
            menus = menuService.findByRoles(roles.parallelStream().filter(item->item.getStatus().equals(1)).map(SysRole::getId).collect(Collectors.toSet()));
        }

//        //三权判定
//        Sys3auth auth = authService.find();
//        if (auth != null && auth.getAdmin1Userid().equals(loginAppUser.getId())) {//设置员
//            Map<String, Object> params = new HashMap<>();
//            params.put("category", "1");
//            List<SysMenu> menus1 = menuService.findMenus(params);
//            menus.addAll(menus1);
//        } else if (auth != null && auth.getAdmin2Userid().equals(loginAppUser.getId())) {//审核员
//            Map<String, Object> params = new HashMap<>();
//            params.put("category", "2");
//            List<SysMenu> menus1 = menuService.findMenus(params);
//            menus.addAll(menus1);
//        } else if (auth != null && auth.getAdmin3Userid().equals(loginAppUser.getId())) {//审计员
//            Map<String, Object> params = new HashMap<>();
//            params.put("category", "3");
//            List<SysMenu> menus1 = menuService.findMenus(params);
//            menus.addAll(menus1);
//        }
        menus = menus.stream().distinct().collect(Collectors.toList());
        List<SysMenu> sysMenus = TreeBuilder(menus);
        return sysMenus;
    }


    /**
     * 删除菜单
     *
     * @param id
     */
    @PreAuthorize("hasAuthority('menu:delete/menus/{id}')")
    @ApiOperation(value = "删除菜单")
    @DeleteMapping("/menus/{id}")
    @LogAnnotation(module = "系统菜单", name = "删除")
    public Result delete(@PathVariable(value = "id") String id) {
        try {
            menuService.delete(id);
            return Result.succeed("操作成功");
        } catch (Exception ex) {
            ex.printStackTrace();
            return Result.failed("操作失败");
        }
    }


    /**
     * 两层循环实现建树
     */
    private static List<SysMenu> TreeBuilder(List<SysMenu> sysMenus) {

        List<SysMenu> menus = new ArrayList<>();
        for (SysMenu sysMenu : sysMenus) {
            if (ObjectUtils.equals("0", sysMenu.getParentId())) {
                menus.add(sysMenu);
            }
            for (SysMenu menu : sysMenus) {
                if (menu.getParentId().equals(sysMenu.getId())) {
                    if (sysMenu.getSubMenus() == null) {
                        sysMenu.setSubMenus(new ArrayList<>());
                    }
                    sysMenu.getSubMenus().add(menu);
                }
            }
        }
        return menus;
    }
}
